package anaglyph;

import java.awt.FlowLayout;
import java.awt.Button;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Panel;
import java.applet.Applet;
import java.util.Enumeration;

import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;

import javax.media.j3d.*;
import javax.swing.BoxLayout;
import javax.swing.JOptionPane;

import scenes.SceneFactory;

abstract class ButtonBar implements ActionListener {
	String[] commands;
	AnaglyphFacade myaf = null;
	Panel toolbarPanel;

	public int getActionIndex(ActionEvent e) { // returns zero based index
		String command = e.getActionCommand();
		int index = 0;
		for (String action : commands) {
			if (action.equals(command))
				return index;
			index++;
		}
		return -1;
	}

	public ButtonBar(String[] commands, AnaglyphFacade af) {
		this.commands = commands;
		this.myaf = af;
		toolbarPanel = new Panel();
		toolbarPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
		for (String command : commands) {
			Button button = new Button(command);
			button.setFocusable(false);
			button.addActionListener(this);
			toolbarPanel.add(button);
		}
	}

	public Panel getToolbarPanel() {
		return toolbarPanel;
	}
}

class AnaglyphSelector extends ButtonBar {
	CanvasConfig mycc = null;

	@Override
	public void actionPerformed(ActionEvent e) {
		int index = getActionIndex(e);
		if (index != -1) {
			mycc.AnaglyphMode = index;
			myaf.refreshScreen();
		}
	}

	public AnaglyphSelector(AnaglyphFacade af, CanvasConfig cc) {
		super(new String[] { "red blue", "red green", "color", "optimized",
				"no anaglyps - left eye", "no anaglyps - right eye" }, af);
		this.mycc = cc;
	}
}

class SceneSelector extends ButtonBar {
	AnaglyphDemo ad;

	@Override
	public void actionPerformed(ActionEvent e) {
		int index = getActionIndex(e);
		if (index != -1) {
			if (index == 3)
				ad.logSceneGraphStat();
			if (index == 4)
				System.exit(0);
			else {
				ad.changeSceneGraph(index);
				myaf.refreshScreen();
			}
		}
	}

	public SceneSelector(AnaglyphFacade af, AnaglyphDemo ad) {
		super(new String[] { "scene 1", "scene 2", "scene 3", "Stat", "Exit" },
				af);
		this.ad = ad;
	}
}

// /////////////////////////////////////////////////////////////////////////////////////////

public class AnaglyphDemo extends Applet {
	/**
	 * 
	 */
	static MainFrame mf;
	private static final long serialVersionUID = 1L;

	private SceneFactory sf;
	private BranchGroup scene;
	private SimpleUniverse u = null;
	private CanvasConfig cc = null;
	private AnaglyphFacade af = null;

	// buttons

	/**
	 * Public no-arg constructor
	 */
	public AnaglyphDemo(CanvasConfig cc) {
		super();
		this.cc = cc;
	}

	public void init() {
		// create objects
		af = new AnaglyphFacade(cc);
		sf = new SceneFactory(this, af);

		// create and fill window layout
		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		AnaglyphSelector anSelector = new AnaglyphSelector(af, cc);
		SceneSelector scSelector = new SceneSelector(af, this);
		add(scSelector.getToolbarPanel());
		add(anSelector.getToolbarPanel());
		this.add(af.GetOnScreenCanvas());

		// create scene graph - view and content
		u = af.CreateAnaglyphUniverse(); // view branch
		scene = sf.CreateScene(sf.GetDefaultSID()); // content branch
		u.addBranchGraph(scene);		
		af.refreshScreen();
	}

	public void changeSceneGraph(int sid) {
		BranchGroup oldscene = scene;
		BranchGroup newscene = sf.CreateScene(sid + 1);
		u.getLocale().replaceBranchGraph(oldscene, newscene);
		scene = newscene;
	}

	public void logSceneGraphStat() {
		String msg = "";
		int count = scene.numChildren();
		Enumeration<?> e = scene.getAllChildren();
		while (e.hasMoreElements()) {
			Node node = (Node) e.nextElement();
			msg += "\n" + node.toString();
		}
		msg += "\nnumChildren: " + count;
		JOptionPane.showMessageDialog(null, msg);
	}

	public void destroy() {
		u.removeAllLocales();
	}

	public static void main(String[] args) {
		assert (true);
		String path = System.getProperty("java.library.path");
		System.out.println("java.library.path = " + path+"\n\n");					
		System.setProperty("j3d.rend", "ogl");
		//System.setProperty("sun.java2d.opengl", "true");
		
		CanvasConfig cc = new CanvasConfig();
		mf = new MainFrame(new AnaglyphDemo(cc), cc.ContainerDimX,
				cc.ContainerDimY);
		mf.addWindowListener(new WindowKiller());
		mf.addKeyListener(new WindowKiller2());
	}
}

class WindowKiller extends WindowAdapter {
	public void windowClosing(WindowEvent e) {
		System.exit(0);
	}
}

class WindowKiller2 extends KeyAdapter {
	@Override
	public void keyTyped(KeyEvent e) {
		System.exit(0);
	}
}